package com.spring.framework.config.bean.model;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * 基于注解的组件的默认作用域都是singleton单例，如果想要指定不同的作用域，可以使用@Scope注解，可以在注解中提供作用
 * 域的名称。
 * <p>
 * ps:@Scope注解仅仅在一系列Component组件注解标注的类和@Bean标注的工厂方法上有效果，scope含有的的作用域和XML配置
 * 的作用域参数一致，就是相当于< bean >标签的scope属性，详情参考XML的配置文章。
 * <p>
 * 通常，我们只会配置singleton和prototype两种作用域，甚至基本不会配置，默认就是singleton。如果要配置，这两个值在
 * ConfigurableBeanFactory 接口中有SCOPE_SINGLETON 和 SCOPE_PROTOTYPE定义好的字面常量值，我们可以直接使用，当
 * 然也可以直接写字符串。
 *
 * @author xuweizhi
 */
@Component
public class ScopeDemo {
	public ScopeDemo() {
		System.out.println("ScopeDemo初始化：" + this);
	}

	/**
	 * 默认就是singleton
	 */
	@Component("scopeO")
	public static class ScopeO {
		public ScopeO() {
			System.out.println("ScopeO初始化：" + this);
		}
	}

	/**
	 * 加上注解不指定作用域也是默认singleton
	 */
	@Component("scopeA")
	@Scope
	public static class ScopeA {
		public ScopeA() {
			System.out.println("ScopeA初始化：" + this);
		}
	}

	/**
	 * 可以通过ConfigurableBeanFactory.SCOPE_SINGLETON引用singleton字符串
	 */
	@Component("scopeB")
	@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
	public static class ScopeB {
		public ScopeB() {
			System.out.println("ScopeB初始化：" + this);
		}
	}

	/**
	 * 可以通过ConfigurableBeanFactory.SCOPE_PROTOTYPE引用prototype字符串
	 */
	@Component("scopeC")
	@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
	@Qualifier
	public static class ScopeC {
		public ScopeC() {
			System.out.println("ScopeC初始化：" + this);
		}
	}


	/**
	 * 默认@Bean就是singleton
	 * 加上注解不指定作用域也是默认singleton
	 */
	@Bean
	@Scope
	public ScopeDemo getScopeDemo1() {
		return new ScopeDemo();
	}

	/**
	 * 指定prototype
	 */
	@Bean
	@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
	public ScopeDemo getScopeDemo2() {
		return new ScopeDemo();
	}
}
